﻿using System.Drawing;
using CamPlug.Api;
using SKYPE4COMLib;
using System;

namespace CamPlug.SkypeConference.Plugin
{
	public class SkypeConferencePlugin : IPlugin
	{
		public const string Name = "Skype conference";
		const double FlashDenominator = 100;
		const double HalfFlashDenominator = FlashDenominator / 2;
		const double FlashDuration = 0.15 * FlashDenominator;


		object SyncRoot = new object();
		Skype SkypeClient;
		PropertiesForm PropertiesForm;

		public CallMonitor CallMonitor { get; private set; }

		public SkypeConferencePlugin()
		{
			SkypeClient = new Skype();
			CallMonitor = new CallMonitor(this.SkypeClient);
		}

		string IPlugin.Name
		{
			get { return Name; }
		}

		public byte[] SaveSettings()
		{
			return new byte[0];
		}

		public void LoadSettings(byte[] settings)
		{
		}

		public void UpdateBitmap(Bitmap bitmap)
		{
			lock (SyncRoot)
			{
				using (var canvas = Graphics.FromImage(bitmap))
				{
					switch (CallMonitor.Status)
					{
						case CallMonitorStatus.AttachedButNotInCall:
							DrawStatusText(bitmap: bitmap, canvas: canvas, statusText: "Not in a call");
							break;

						case CallMonitorStatus.AttachRequestPending:
							DrawStatusText(bitmap: bitmap, canvas: canvas, statusText: "Accept attach request in Skype!");
							break;

						case CallMonitorStatus.AttachRequestRefused:
							DrawStatusText(bitmap: bitmap, canvas: canvas, statusText: "Skype refused attach request");
							break;

						case CallMonitorStatus.NotAttached:
							DrawStatusText(bitmap: bitmap, canvas: canvas, statusText: "Waiting for Skype to sign in");
							break;

						default:
							if (CallMonitor.IsInCall)
							{
								DrawStatus(bitmap: bitmap, canvas: canvas);
								DrawTotals(bitmap: bitmap, canvas: canvas);
							}
							break;
					}

				}
			}
		}

		void DrawStatusText(Bitmap bitmap, Graphics canvas, string statusText)
		{
			Font font = new Font(new FontFamily("Arial"), 32);
			var textSize = canvas.MeasureString(text: statusText, font: font);
			var textLocation = new PointF(bitmap.Width / 2 - textSize.Width / 2, bitmap.Height / 2 - textSize.Height / 2);
			var textRect = new RectangleF(location: textLocation, size: textSize);
			textRect.Inflate(new SizeF(2, 2));
			canvas.FillRectangle(brush: Brushes.Black, rect: textRect);
			canvas.DrawString(s: statusText, font: font, brush: Brushes.White, point: textLocation);
		}

		public void ShowPropertiesForm()
		{
			if (PropertiesForm == null)
				PropertiesForm = new PropertiesForm(this);
			if (!PropertiesForm.Visible)
				PropertiesForm.Show();
			PropertiesForm.BringToFront();
		}

		public void ShuttingDown()
		{
			lock (SyncRoot)
			{
				SkypeClient = null;
				var originalCallMonitor = CallMonitor;
				CallMonitor = null;
				originalCallMonitor.Dispose();
			}
		}

		void DrawStatus(Bitmap bitmap, Graphics canvas)
		{
			TimeSpan currentDuration = TimeSpan.Zero;
			TimeSpan totalDuration = TimeSpan.Zero;
			Bitmap backdropBitmap = null;
			PointF textOffset = PointF.Empty;
			float backdropScale = 1;

			switch (CallMonitor.Status)
			{
				case CallMonitorStatus.Talking:
					backdropBitmap = Properties.Resources.SpeechBubble;
					currentDuration = CallMonitor.CurrentTalkingDuration;
					totalDuration = CallMonitor.TotalTalkingDuration;
					backdropScale = 0.25f;
					textOffset = new PointF(-1f, -6f);
					break;

				case CallMonitorStatus.WaitingToTalk:
					backdropBitmap = Properties.Resources.RaisedHand;
					currentDuration = CallMonitor.CurrentWaitingToTalkDuration;
					if (currentDuration.TotalSeconds > 10)
					{
						double flashModulo = currentDuration.TotalSeconds * FlashDenominator % FlashDenominator;
						if (flashModulo > FlashDenominator - FlashDuration)
							return;
						if (currentDuration.TotalSeconds > 60)
						{
							if (flashModulo >= HalfFlashDenominator - FlashDuration && flashModulo < HalfFlashDenominator)
								return;
						}
					}
					totalDuration = CallMonitor.TotalWaitingToTalkDuration;
					backdropScale = 0.45f;
					textOffset = new PointF(-12f, -1f);
					break;

				default:
					return;
			}

			float backdropWidth = backdropBitmap.Width * backdropScale;
			float backdropHeight = backdropBitmap.Height * backdropScale;
			int backdropLeft = 0;
			float backdropTop = bitmap.Height - backdropHeight;
			canvas.DrawImage(backdropBitmap, new RectangleF(backdropLeft, backdropTop, backdropWidth, backdropHeight));

			string text = string.Format("{0}:{1:00}", Math.Floor(currentDuration.TotalMinutes), currentDuration.Seconds);
			Font font = new Font(new FontFamily("Arial"), 17);
			SizeF textSize = canvas.MeasureString(text, font);
			SizeF halfTextSize = new SizeF(textSize.Width / 2f, textSize.Height / 2f);
			var centerOfBackdrop = new PointF(backdropLeft + backdropWidth / 2f, backdropTop + backdropHeight / 2f);
			var textPosition = new PointF(centerOfBackdrop.X - halfTextSize.Width + textOffset.X, centerOfBackdrop.Y - halfTextSize.Height + textOffset.Y);
			canvas.DrawString(text, font, Brushes.Black, textPosition);
		}

		void DrawTotals(Bitmap bitmap, Graphics canvas)
		{
			var font = new Font(new FontFamily("Arial"), 24);
			TimeSpan totalTalkingDuration = CallMonitor.TotalTalkingDuration;
			string text = totalTalkingDuration.ToString("hh\\:mm\\:ss");
			SizeF textSize = canvas.MeasureString(text, font);
			PointF textLocation = new PointF(bitmap.Width - textSize.Width - 1, bitmap.Height - textSize.Height - 1);
			RectangleF textBackgroundRectangle = new RectangleF(textLocation.X - 1, textLocation.Y - 1, textSize.Width + 2, textSize.Height + 2);
			canvas.FillRectangle(Brushes.Black, textBackgroundRectangle);
			canvas.DrawString(text, font, Brushes.Silver, textLocation);
		}


	}
}
